/**
 * 2017年2月21日
 * 疯狂赛车
 * 玩家信息管理
 */

var waterfall = require('async').waterfall;
var pomelo = require('pomelo');
var eachLimit = require('async').eachLimit;

var log = console.log;

var consts = require('./consts');
var userDao = require('../../dao/userDao');
var playerUtil = require('../util/player');
var client = pomelo.app.get('redisUser');

var mysql = userDao;

function PlayerManager(roomObj) {
    this.roomObj = roomObj;
    this.playerData = {};
    this.playerNum = 0;

    this.bidData = {};  // 下注信息容器,每一局开始前初始化
}

var pro = PlayerManager.prototype;

/**
 *计算结果，不做记录
 */
pro.calcResultOnly = function (odds, cb) {
    console.log('进入计算结果     >>>>>>>>>>>>>>>>>>>>>>');

    var self = this;
    var bidData = self.bidData;
    var playerData = self.playerData;
    var coinChange = {};  // 金钱变动容器

    var existsBid = 0,
        playerId,
        bidRecord, // 下注记录
        bidCoin = 0,  // 押注的金钱
        taxCoin = 0,  // 交的税
        coinGain = 0,  // 赚的钱
        coinChangeNum = 0;
    var room = this.roomObj;

    var tax = room.tax,
        realReturn,
        bankerReturn = 0,
        sysGain = 0,
        roundRec = {
            userCount: 0,
            bidCoin: 0,
            tax: 0
        };

    // odds = { '1': 3, '2': 10, '3': -1, '4': 6 };
    // bidData = { '1004': { '0': 300, '1': 300, '2': 300, '3': 500 } };
    for (playerId in bidData) {
        existsBid = 1;
        roundRec.userCount++;
        bidRecord = bidData[playerId];
        // bidRecord = { '0': 300, '1': 300, '2': 300, '3': 500 };
        if (!coinChange[playerId]) {
            coinChange[playerId] = {
                playerId,
                coinChange: 0,
                taxCoin: 0,
                bidRecord
            };
        }

        for (var k in bidRecord) {
            bidCoin = bidRecord[k];
            roundRec.bidCoin += bidCoin;
            if (odds[k] > 0) {
                // 玩家赚钱，净数额是 下注数量 * (赔率 - 1)
                coinGain += bidCoin * (odds[k] - 1);
            }
            else {
                // 玩家赔掉下的筹码
                coinGain -= bidCoin;
            }
        }

        if (coinGain > 0) {
            taxCoin = (tax === 0) ? 0 : coinGain * tax / 100;
            coinChangeNum = coinGain - taxCoin;
            bankerReturn += coinChangeNum;  // 庄家赔的钱
        }
        else {
            taxCoin = 0;
            coinChangeNum = coinGain;
            bankerReturn -= coinChangeNum;
        }

        roundRec.tax += taxCoin;
        sysGain += taxCoin;
        // 变更玩家金钱
        playerData[playerId].coin += coinChangeNum;

        coinChange[playerId].coinChange = coinChangeNum;
        coinChange[playerId].taxCoin = taxCoin;
        coinChange[playerId].coin = playerData[playerId].coin;
    }  // 各个玩家计算完成

    var bankerId, bankerTax, bankerGain;

    if (room.curBanker > 0) {
        log('此局有用户坐庄！');

        bankerId = room.curBanker;

        coinChange.banker = { coinChange: 0 };

        if (bankerReturn > 0) {
            // 庄家赔钱
            playerData[bankerId].coin -= bankerReturn;
            coinChange.banker.coinChange -= bankerReturn;
            coinChange.banker.taxCoin = 0;
        }
        else if (bankerReturn < 0) {
            // 庄家赚钱
            bankerTax = (tax === 0) ? 0 : ((-bankerReturn) * tax / 100);
            bankerGain = (-bankerReturn) - bankerTax;

            sysGain += bankerTax;
            roundRec.tax += bankerTax;

            coinChange.banker.taxCoin = bankerTax;
            coinChange.banker.coinChange = bankerGain;
            playerData[bankerId].coin += bankerGain;
        }
        else {
            // 庄家不赚不赔
            coinChange.banker.coinChange = 0;
            coinChange.banker.taxCoin = 0;
        }

        coinChange.banker.coin = playerData[bankerId].coin;
        // 更新庄的分数
        room.curBankerScore += coinChange.banker.coinChange;
        coinChange.banker.score = room.curBankerScore;
        coinChange.banker.round = room.curBankerRound;
    }

    roundRec.sysGain = sysGain;
    roundRec.existsBid = existsBid;

    this.recordResult(coinChange, roundRec, cb);
};

// 记录结果
pro.recordResult = function (coinChange, roundRec, cb) {
    var self = this;

    // 如果无人下注，那么就不记录这一局的结果
    if (!roundRec.existsBid) {
        // 要返回coinChange 用于可能的庄家局数递增返回数据
        cb(null, coinChange);
        return;
    }

    var room = this.roomObj;
    var playerData = this.playerData;

    var bankerId = room.curBanker || 0;
    var bankerName = bankerId > 0 ? playerData[bankerId].playerName : 'none';

    var gameId = room.gameId;
    var curCards = room.curResult;

    log('当前的牌是：', curCards);

    // 首先插入牌局记录表，并通过返回值获取到新增的id
    var sql = 'INSERT INTO game_round (gameId, roomName, userId, userName, card, cardResult, userCount, bidCoin, tax, platformProfit, duration, addTime) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW())';
    var args = [gameId, room.name, bankerId, bankerName, curCards, curCards, roundRec.userCount, roundRec.bidCoin, roundRec.tax, roundRec.sysGain, room.xiaZhuTime];

    var insertId;

    log('插入数据', args);

    mysql.query(sql, args, function (err, rows) {
        if (err) {
            cb(err, {});
            throw new Error('caught exception when calcResult in playerManager.js');
        }
        insertId = rows.insertId;
        eachLimit(coinChange, 3,
            function (p, callback) {

                var playerId = p.playerId === 'banker' ? room.curBanker : p.playerId;
                var player = playerData[playerId];
                var playerName = player.playerName;
                var isRobot = player.isRobot;
                var bidRecord = JSON.stringify(p.bidRecord) || 'banker';

                delete p.bidRecord;
                var result = 0;

                if (p.coinChange > 0) {
                    result = 1;
                }
                else if (p.coinChange < 0) {
                    result = -1;
                }

                waterfall([
                    function (wcb) {
                        // 插入个人流水记录表
                        // 机器人的不再记录
                        if (isRobot) {
                            wcb(null);
                            return;
                        }
                        // log('mysql里面的: ', playerId);
                        sql = 'insert into game_queue (gameId, userId, userName, bidRecord, coinChange, tax, result, roundId, addTime) values (?, ?, ?, ?, ?, ?, ?, ?, now())';
                        // var curTime = new Date().getTime();
                        args = [gameId, playerId, playerName, bidRecord, p.coinChange, p.taxCoin, result, insertId];
                        console.log('args >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>');
                        console.log(args);

                        mysql.query(sql, args, function (err, rows, field) {
                            if (err) {
                                wcb(err);
                            }
                            else {
                                wcb(null);
                            }
                        });
                    },
                    function (wcb) {
                        if (isRobot) {
                            wcb(null);
                            return;
                        }
                        // 跳过，防止改变真实用户金钱缓存
                        var coinKey = 'coin' + playerId;

                        // log('结算之前', coinKey, '改变了：');
                        client.incrby(coinKey, p.coinChange, function (err, rel) {
                            if (err) {
                                wcb(err);
                            }
                            else {
                                // log('结算', coinKey, '改变了：', p.coinChange);
                                wcb(null);
                            }
                        });
                    }
                ],
                    function (err) {
                        if (!err) {
                            callback(null);
                        }
                        else {
                            callback(err);
                        }
                    }
                );  // end of waterfall

            },
            function (err) {
                if (err) {
                    console.log(err);
                    cb(err, {});
                    throw new Error('caught exception when calcResult in playerManager.js');
                }
                else {
                    log(coinChange);
                    cb(null, coinChange); // room.calcResult cb
                }
            });
    });

};

// 更新用户的局数和金钱到mysql
// 因为用到了异步，所以不知道是不是在下一次开始下注前结束了操作。
pro.updatePlayerRounds = function (roomCalcResultCb) {
    // cb();
    var self = this;
    var playerIdList = [];

    roomCalcResultCb();
};


/**
 * 2016年12月26日
 * 用户管理添加用户
 */
PlayerManager.prototype.addPlayer = function (data, callback) {
    console.log('PlayerManage.addPlayer caught ----------------');
    var self = this;
    var gameId = data.gameId;
    var playerId = data.playerId;
    var ip = data.ip;
    var isRobot = data.isRobot;


    var players = this.playerData;
    var player = {};

    var minCoin = consts.ROOM.MIN_COIN;

    playerUtil.playerLogin(data, function (err, rel) {
        if (err) {
            console.log(err);
            callback(err);
        }
        else {
            player = rel;
            players[playerId] = player;
            player.isRobot = false;

            // 如果在掉线玩家名单里，就删掉
            var idx = self.roomObj.offlinePlayer.indexOf(playerId);

            if (idx > -1) {
                self.roomObj.offlinePlayer.splice(idx, 1);
            }

            self.playerNum++;

            callback(null);
        }
    });
};

/**
 * 用户离开
 */
PlayerManager.prototype.kickPlayer = function (data) {
    var players = this.playerData;
    var playerId = data.playerId;
    var room = this.roomObj;

    // 如果是下注时间并且已经下注，不能删掉，否则无法结算
    if (room.getGameStatus().gameStatus === consts.GAME.STATUS.XIAZHU && this.bidData[playerId]) {
        room.offlinePlayer.push(playerId);
    }
    else {
        delete players[playerId];

        var key = 'onlineGameUser';

        client.hdel(key, playerId, function (err, rel) {
            if (err) {
                log(err);
                throw new Error('redis err:', err);
            }
            else {
                log('玩家%s已经退出游戏%s', playerId, room.gameId);
            }
        });

        // 玩家数量记录减少
        this.playerNum--;
    }

    return true;
};


/**
 * 2016年12月26日
 * 根据id获取用户信息
 */
PlayerManager.prototype.getPlayerData = function (playerId) {
    console.log('PlayerManage.getPlayerData ---------------');
    var player, ret;

    if (this.playerData[playerId]) {
        player = this.playerData[playerId];
        ret = {
            playerId,
            name: player.playerName,
            coin: player.coin,
            score: player.score,
            roundCount: player.roundCount
        };
    }
    return ret || { name: 'guest', coin: 0, score: 0, roundCount: 0 };
};

/**
 * 检查用户是否在此房间里
 */
PlayerManager.prototype.isPlayerInRoom = function (playerId) {
    var players = this.playerData;

    return players[playerId];
};

// 返回用户列表，从内存中获取数据
// in: null
// out: [{playerId, name, coin}, ...]   order by coin desc
PlayerManager.prototype.getPlayerList = function () {
    console.log('PlayerManager.getPlayerList caught >>>>>>>>>>>>>>>>>>>>>>>>>>>>>');
    var playerData = this.playerData;

    function sortByCoin(p1, p2) {
        return p2.coin - p1.coin;
    }

    var list = [];

    for (var playerId in playerData) {
        list.push({
            playerId,
            name: playerData[playerId].playerName,
            coin: playerData[playerId].coin
        });
    }
    // list.sort(sortByCoin);

    console.log(list);
    return list;
};

/**
 * Expose 'playerManager' constructor.
 */
module.exports = PlayerManager;
